; 中断处理程序
[bits 32]
%define ERROR_CODE nop
%define ZERO push 0

extern idt_table
extern put_int
section .data                                  
global intr_entry_table
intr_entry_table:                               ; 中断处理程序地址数组

%macro VECTOR 2                                 ; VECTOR 有两个参数, 中断向量号和错误码是否压栈
section .text
intr%1entry:

    %2
    ; 保存上下文环境
    push ds      ; 保存数据段基址                                
    push es      ; 保存附加数据段基址
    push fs
    push gs 
    pushad       ; 压入32位寄存器eax, ecx, edx, ebx, esp, ebp, esi, edi

    ; 8259A相关处理
    mov al, 0x20                                ; 中断结束命令EOI:0010_1111
    out 0xa0, al                                ; 向从片发送
    out 0x20, al                                ; 向主片发送
    
    push %1                    ; 压入中断号

    call [idt_table + %1*4]    ; 调用对应的C中断处理程序
    jmp intr_exit

section .data
    dd intr%1entry                               ; 存储各个中断入口程序地址, 形成intr_entry_table数组

%endmacro

section .text
global intr_exit
intr_exit:
; 恢复上下文环境
    add esp, 4    ; 跳过中断号
    popad         ; 恢复通用寄存器
    pop gs
    pop fs
    pop es
    pop ds
    add esp, 4     ; 跳过error_code
    iretd

VECTOR 0x00, ZERO
VECTOR 0x01, ZERO
VECTOR 0x02, ZERO
VECTOR 0x03, ZERO
VECTOR 0x04, ZERO
VECTOR 0x05, ZERO
VECTOR 0x06, ZERO
VECTOR 0x07, ZERO
VECTOR 0x08, ERROR_CODE
VECTOR 0x09, ZERO
VECTOR 0x0a, ERROR_CODE
VECTOR 0x0b, ERROR_CODE
VECTOR 0x0c, ZERO
VECTOR 0x0d, ERROR_CODE
VECTOR 0x0e, ERROR_CODE
VECTOR 0x0f, ZERO
VECTOR 0x10, ZERO
VECTOR 0x11, ERROR_CODE
VECTOR 0x12, ZERO
VECTOR 0x13, ZERO
VECTOR 0x14, ZERO
VECTOR 0x15, ZERO
VECTOR 0x16, ZERO
VECTOR 0x17, ZERO
VECTOR 0x18, ERROR_CODE
VECTOR 0x19, ZERO
VECTOR 0x1a, ZERO
VECTOR 0x1b, ZERO
VECTOR 0x1c, ZERO
VECTOR 0x1d, ERROR_CODE
VECTOR 0x1e, ERROR_CODE 
VECTOR 0x1f, ZERO
VECTOR 0x20, ZERO    ; 外部中开始, 8295a控制管理
VECTOR 0x21, ZERO    ; 键盘中断对应入口 
VECTOR 0x22, ZERO
VECTOR 0x23, ZERO
VECTOR 0x24, ZERO
VECTOR 0x25, ZERO
VECTOR 0x26, ZERO
VECTOR 0x27, ZERO
VECTOR 0x28, ZERO
VECTOR 0x29, ZERO
VECTOR 0x2a, ZERO
VECTOR 0x2b, ZERO
VECTOR 0x2c, ZERO
VECTOR 0x2d, ZERO
VECTOR 0x2e, ZERO
VECTOR 0x2f, ZERO

;;;;;;;;;;;;;0x80
extern syscall_table
section .text
global syscall_handler

syscall_handler:
    push 0
    push ds
    push es
    push fs
    push gs
    pushad

    push 0x80

    push edx
    push ecx
    push ebx
    
    call [syscall_table + eax*4]
    add esp, 12

    mov [esp + 8*4], eax
    jmp intr_exit
